package cn.weiyan.dtx.tccdemo.bank1.server.impl;

import cn.weiyan.dtx.tccdemo.bank1.dao.AccountInfoDao;
import cn.weiyan.dtx.tccdemo.bank1.server.AccountInfoServer;
import cn.weiyan.dtx.tccdemo.bank1.spring.Bank2Client;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.dromara.hmily.core.concurrent.threadlocal.HmilyTransactionContextLocal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author misterWei
 * @create 2020年02月14号:17点41分
 * @mailbox mynameisweiyan@gmail.com
 */
@Service
@Slf4j
@SuppressWarnings("all")
public class AccountInfoServerImpl implements AccountInfoServer {

    @Autowired
    private AccountInfoDao accountInfoDao;

    // 远程调用服务
    @Autowired
    private Bank2Client bank2Client;


    @Transactional
    // 该Hmily 方法标注在那个方法上的时候就说明该方法是一个try方法,然后置顶 confirm || cancel 方法
    @Hmily(confirmMethod = "commit",cancelMethod = "rollback")
    @Override
    public void updateAccountBalance(String accountNo, Double amount) {
      //获取全局事务管理器对象
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("Bank1  Service 的try 执行 全局事务ID 为:" + transId);
        // 幂等性校验
        if (accountInfoDao.isExistTry(transId) > 0) {

            log.warn("Bank1 Service 已经执行try，无需重复执行，事务id:{} "+transId);
            return;
        }
        // 悬挂校验
        //try悬挂处理
        if(accountInfoDao.isExistCancel(transId)>0 || accountInfoDao.isExistConfirm(transId)>0)
        {
            log.info(" Bank1 Service 已经执行confirm或cancel，悬挂处理，事务id:{} "+transId );
            return ;
        }

        // 执行业务逻辑
        if (accountInfoDao.subtractAccountBalance(accountNo,amount) <= 0){
            // 扣减失败,进行回滚
            throw  new RuntimeException(" Bank1 扣减失败 余额不够");
        }
        //增加本地事务try成功记录，用于幂等性控制标识
        accountInfoDao.addTry(transId);

        //远程调用
        if (!bank2Client.transfer(amount)) {
            throw new RuntimeException("远程调用失败...");
        }

        // 自定义异常
        if (amount == 3D){
            throw new RuntimeException("自定义异常返回了...");
        }
        log.info("Bank1  Service 的try 执行结束");
    }

    public void commit(String accountNo, Double amount){
        //获取全局事务管理器对象
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();

        log.info(" Bank1 confirm 已经执行 事务id:{} "+transId );

    }
    @Transactional
    public void rollback(String accountNo, Double amount){


        //获取全局事务管理器对象
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        if (accountInfoDao.isExistTry(transId) <=0) {
            //预防空回滚.

            log.info(" Bank1 try 没有执行- 不可回滚 事务id:{} "+transId );
            return;
        }
        //进行回滚
        accountInfoDao.addAccountBalance(accountNo,amount);

        //添加cancel日志，用于幂等性控制标识
        accountInfoDao.addCancel(transId);

    }
}
